/*
 * guild.cpp
 *
 *  Created on: Jul 30, 2014
 *      Author: killerg
 */

#include "../server_deps.h"
#include "guild.h"
#include "player_mgr.h"
#include "../server.h"

void member_t::fill_info(cs::OGuildMember* info) {
	auto playerinfo = g_playermgr->infos.get(playerid);
	assert(playerinfo);

    info->set_name(playerinfo->name);
    info->set_id(playerid);
    info->set_combatforce(playerinfo->total_combat_force);
    info->set_contrib(contrib);
    info->set_pos(pos);
}

void guild_t::add_member(int64_t playerid, EGuildPos pos) {
	assert(members.count(playerid) == 0);
	member_t* member = new member_t;
	member->contrib = 0;
	member->playerid = playerid;
	member->lastlogon = -1;
	member->pos = pos;
	members[playerid] = member;

	if (pos == EGP_Head)
		leader = playerid;
}

member_t* guild_t::get_member(int64_t playerid) {
	return members.get(playerid);
}

void guild_t::del_member(int64_t playerid) {
	assert(members.count(playerid) > 0);

	auto member = members.get(playerid);
	members.erase(playerid);
	if (member->pos == EGP_Head)
		update_leader();

	delete member;
}

void guild_t::update_leader() {
	for (auto itr : members) {
		if (itr.second->pos == EGP_Head) {
			leader = itr.first;
			break;
		}
	}
}

void guild_t::add_contrib(int64_t playerid, int32_t contrib) {
	auto member = get_member(playerid);
	if (!member)
		return;

	member->contrib += contrib;
	contrib += contrib;
}

void guild_t::fill_info(cs::OGuildInfo* info) {
	assert(info);
	auto leaderinfo = g_playermgr->infos.get(leader);
	assert(leaderinfo);

	info->set_leader(leaderinfo->name);
	info->set_id(id);
	info->set_name(name);
	info->set_membernum(members.size());
	info->set_contrib(contrib);
	info->set_rank(rank);
	info->set_intro(intro);
}

bool guild_t::initr(const rj::Value &json) {
	assert(json.IsObject());
	id = json["id"].GetInt();
	name = json["name"].GetString();
	intro = json["intro"].GetString();
	contrib = json["contrib"].GetInt();

	const rj::Value &rj_members = json["members"];
	assert(rj_members.IsArray());
	for (int i=0; i<rj_members.Size(); ++i) {
		const rj::Value &rj_member = rj_members[i];
		auto member = new member_t;
		member->playerid = rj_member["id"].GetInt64();
		member->pos = rj_member["pos"].GetInt();
		member->contrib = rj_member["contrib"].GetInt();
		member->lastlogon = rj_member["lastlogon"].GetInt();
		members[member->playerid] = member;

		g_guildmgr->on_player_guildid(member->playerid, id);
	}

	const rj::Value &rj_appliers = json["appliers"];
	assert(rj_appliers.IsArray());
	for (int i=0; i<rj_appliers.Size(); ++i) {
		appliers.insert(rj_appliers[i].GetInt64());
	}

	return true;
}

bool guild_t::saver(rj::Value &json, rj::Document::AllocatorType& al) {
	json.SetObject();
	json.AddMember("id", id, al);
	json.AddMember("name", name.c_str(), al);
	json.AddMember("intro", intro.c_str(), al);
	json.AddMember("contrib", contrib, al);

	rj::Value rj_members;
	rj_members.SetArray();

	rj::Value rj_member;
	rj_member.AddMember("id", -1, al);
	rj_member.AddMember("pos", EGP_Normal, al);
	rj_member.AddMember("contrib", 0, al);
	rj_member.AddMember("lastlogon", 0, al);
	for (auto itr : members) {
		rj_member["id"] = itr.second->playerid;
		rj_member["pos"] = itr.second->pos;
		rj_member["contrib"] = itr.second->contrib;
		rj_member["lastlogon"] = itr.second->lastlogon;
		rj_members.PushBack(rj_member, al);
	}
	json.AddMember("members", rj_members, al);

	rj::Value rj_appliers;
	rj_appliers.SetArray();
	for (auto applier : appliers)
		rj_appliers.PushBack(applier, al);
	json.AddMember("appliers", rj_appliers, al);

	return true;
}

bool guild_t::init(const Json::Value &json) {
	id = json["id"].asInt();
	name = json["name"].asCString();
	intro = json["intro"].asCString();
	contrib = json["contrib"].asInt();

	const auto &js_members = json["members"];
	for (const auto &js_member : js_members) {
		auto member = new member_t;
		member->playerid = js_member["id"].asInt64();
		member->pos = js_member["pos"].asInt();
		member->contrib = js_member["contrib"].asInt();
		member->lastlogon = js_member["lastlogon"].asInt();
		members[member->playerid] = member;

		g_guildmgr->on_player_guildid(member->playerid, id);
	}

	const auto &js_appliers = json["appliers"];
	for (const auto &js_applier : js_appliers)
		appliers.insert(js_applier.asInt64());

	return true;
}
bool guild_t::save(Json::Value &json) {
	json["id"] = id;
	json["name"] = name;
	json["intro"] = intro;
	json["contrib"] = contrib;

	auto &js_members = json["members"];
	Json::Value js_member;
	for (auto itr : members) {
		js_member["id"] = Json::Int64(itr.second->playerid);
		js_member["pos"] = itr.second->pos;
		js_member["contrib"] = itr.second->contrib;
		js_member["lastlogon"] = itr.second->lastlogon;

		js_members.append(js_member);
	}

	auto &js_appliers = json["appliers"];
	for (auto applier : appliers)
		js_appliers.append(Json::Int64(applier));

	return true;
}

void guildmgr_t::on_player_guildid(int64_t playerid, int32_t guildid) {
	if (guildid >= 0)
		player2guild[playerid] = guildid;
	else
		player2guild.erase(playerid);
}

void guildmgr_t::add_rank(guild_t* guild) {
	rank.push_back(guild);
}
void guildmgr_t::del_rank(guild_t* guild) {
	auto itr = std::find(rank.begin(), rank.end(), guild);
	if (itr != rank.end())
		rank.erase(itr);
}

bool guildmgr_t::init() {
	return true;
}
void guildmgr_t::destroy() {

}
void guildmgr_t::update(double dt) {
	static double _rank_timer = 0.0f;
	if ((_rank_timer -= dt) < 0.0f) {
		_rank_timer = 10*60.0f;

		std::sort(rank.begin(), rank.end(), [](const guild_t* lhs, const guild_t* rhs)->bool{
			return lhs->contrib > rhs->contrib;
		});

		int len = rank.size();
		for (int i=0; i<len; ++i)
			rank[i]->rank = i;
	}
}
